home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / muzsrc1.zip / BLOCK.CPP < prev    next >
C/C++ Source or Header  |  1992-07-21  |  10KB  |  267 lines

  1. // **********************************************
  2. // File: BLOCK.CPP
  3. // Block operations module
  4.  
  5. #include "muzika.h"
  6.  
  7. int markBeginStaff = -1, markBeginX; // Staff and X of mark beginning
  8. int markEndStaff = -1, markEndX;  // Staff and X of mark end
  9.  
  10. // **********************************************
  11. // MarkBlock marks a block by copying the parameters
  12. // to the marking variables.
  13. // To actually reverse-video the marked area
  14. // is a job of the PaintEditWindow function.
  15.  
  16. void MarkBlock(int staffFrom, int Xfrom, int staffTo, int Xto)
  17. {
  18.   Part &p = *((Part *) &melody.part[displayedPart]);
  19.   markBeginStaff = staffFrom/p.multiplicity()*p.multiplicity();
  20.   markBeginX = Xfrom;
  21.   markEndStaff = staffTo/p.multiplicity()*p.multiplicity();
  22.   markEndX = Xto;
  23. }
  24.  
  25. // **********************************************
  26. // UnmarkBlock unmarks a block by setting the marking variables
  27. // to impossible values.
  28.  
  29. void UnmarkBlock()
  30. {
  31.   markBeginStaff = markEndStaff = -1;
  32. }
  33.  
  34. // **********************************************
  35. // CutBlock cuts the marked block to the clipboard.
  36.  
  37. void CutBlock()
  38. {
  39.   // Allocate a memory block (initially of 32K) for the cut operation
  40.   GLOBALHANDLE hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DISCARDABLE, 32767);
  41.   char far *clipboardStart = GlobalLock(hMem);
  42.   char far *clipboard = clipboardStart;
  43.   Part &p = *((Part *) &melody.part[displayedPart]);
  44.  
  45.   // Write the marked block size into the clipboard
  46.   *((int far *) clipboard)++ = p.multiplicity();
  47.   *((int far *) clipboard)++ = markEndStaff-markBeginStaff;
  48.   *((int far *) clipboard)++ = markBeginX;
  49.   *((int far *) clipboard)++ = markEndX;
  50.  
  51.   // Write the musical object information into the clipboard
  52.   for (int staffIndex = markBeginStaff;
  53.     staffIndex/p.multiplicity()*p.multiplicity() <= markEndStaff;
  54.     ++staffIndex) {
  55.     Staff &s = *((Staff *) &p.staff[staffIndex]);
  56.  
  57.     // Cut the point objects:
  58.     // do nothing with unmarked objects,
  59.     // then clip and destroy the marked ones.
  60.     // An object writes its own information to the clipboard
  61.     // in the virtual clipOn function.
  62.     for (int objectIndex = 0;
  63.       objectIndex < s.pointObject.number() &&
  64.         staffIndex/p.multiplicity() == markBeginStaff/p.multiplicity() &&
  65.         ((PointObject *) &s.pointObject[objectIndex])->X() < markBeginX;
  66.       ++objectIndex);
  67.     while (objectIndex < s.pointObject.number() &&
  68.       (staffIndex/p.multiplicity() < markEndStaff/p.multiplicity() ||
  69.         ((PointObject *) &s.pointObject[objectIndex])->X() <= markEndX)) {
  70.       ((PointObject *) &s.pointObject[objectIndex])->clipOn((void far *) clipboard);
  71.       s.pointObject.destroy(objectIndex);
  72.     }
  73.  
  74.     // Cut the continuous objects, similarly to the point ones
  75.     for (objectIndex = 0;
  76.       objectIndex < s.continuousObject.number() &&
  77.         staffIndex/p.multiplicity() == markBeginStaff/p.multiplicity() &&
  78.         ((ContinuousObject *) &s.continuousObject[objectIndex])->Xleft() < markBeginX;
  79.       ++objectIndex);
  80.     while (objectIndex < s.continuousObject.number() &&
  81.       (staffIndex/p.multiplicity() < markEndStaff/p.multiplicity() ||
  82.         ((ContinuousObject *) &s.continuousObject[objectIndex])->Xright() <= markEndX)) {
  83.       ((ContinuousObject *) &s.continuousObject[objectIndex])->clipOn((void far *) clipboard);
  84.       s.continuousObject.destroy(objectIndex);
  85.     }
  86.  
  87.     // Put an end-of-staff marker
  88.     *clipboard++ = STAFF;
  89.   }
  90.  
  91.   // Erase the fully marked staves
  92.   if (markEndStaff-markBeginStaff >= 2*p.multiplicity()) {
  93.     int staffDiff = ((Staff *) &p.staff[markEndStaff])->Y()-
  94.       ((Staff *) &p.staff[markBeginStaff+1])->Y();
  95.     for (staffIndex = markBeginStaff+p.multiplicity();
  96.       staffIndex < markEndStaff;
  97.       ++staffIndex)
  98.       p.staff.destroy(staffIndex);
  99.     for (; staffIndex < p.staff.number(); ++staffIndex)
  100.       ((Staff *) &p.staff[staffIndex])->Y() -= staffDiff;
  101.   }
  102.  
  103.   // Unmark the block once the cut operation is finished
  104.   UnmarkBlock();
  105.  
  106.   // Reallocate the 32K block to the actually needed size
  107.   GlobalUnlock(hMem);
  108.   GlobalReAlloc(hMem, clipboard-clipboardStart, 0);
  109.  
  110.   // Set a clipboard handle to point to the cut block information
  111.   OpenClipboard(hMainWnd);
  112.   EmptyClipboard();
  113.   SetClipboardData(CF_PRIVATEFIRST, hMem);
  114.   CloseClipboard();
  115. }
  116.  
  117. // **********************************************
  118. // CopyBlock copies the marked block to the clipboard.
  119.  
  120. void CopyBlock()
  121. {
  122.   // Allocate a memory block (initially of 32K) for the copy operation
  123.   GLOBALHANDLE hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DISCARDABLE, 32767);
  124.   char far *clipboardStart = GlobalLock(hMem);
  125.   char far *clipboard = clipboardStart;
  126.   Part &p = *((Part *) &melody.part[displayedPart]);
  127.  
  128.   // Write the marked block size into the clipboard
  129.   *((int far *) clipboard)++ = p.multiplicity();
  130.   *((int far *) clipboard)++ = markEndStaff-markBeginStaff;
  131.   *((int far *) clipboard)++ = markBeginX;
  132.   *((int far *) clipboard)++ = markEndX;
  133.  
  134.   // Write the musical object information into the clipboard
  135.   for (int staffIndex = markBeginStaff;
  136.     staffIndex/p.multiplicity()*p.multiplicity() <= markEndStaff;
  137.     ++staffIndex) {
  138.     Staff &s = *((Staff *) &p.staff[staffIndex]);
  139.  
  140.     // Clip the point objects.
  141.     // Each object writes its own information
  142.     // in the virtual clipOn function.
  143.     for (int objectIndex = 0; objectIndex < s.pointObject.number();
  144.       ++objectIndex) {
  145.       PointObject &obj = *((PointObject *) &s.pointObject[objectIndex]);
  146.       if ((staffIndex/p.multiplicity() > markBeginStaff/p.multiplicity() ||
  147.         obj.X() >= markBeginX) &&
  148.         (staffIndex/p.multiplicity() < markEndStaff/p.multiplicity() ||
  149.         obj.X() <= markEndX))
  150.         obj.clipOn((void far *) clipboard);
  151.     }
  152.  
  153.     // Clip the continuous objects, similarly to the point ones
  154.     for (objectIndex = 0; objectIndex < s.continuousObject.number();
  155.       ++objectIndex) {
  156.       ContinuousObject &obj =
  157.         *((ContinuousObject *) &s.pointObject[objectIndex]);
  158.       if ((staffIndex/p.multiplicity() > markBeginStaff/p.multiplicity() ||
  159.         obj.Xleft() >= markBeginX) &&
  160.         (staffIndex/p.multiplicity() < markEndStaff/p.multiplicity() ||
  161.         obj.Xright() <= markEndX))
  162.         obj.clipOn((void far *) clipboard);
  163.     }
  164.  
  165.     // Put an end-of-staff marker
  166.     *clipboard++ = STAFF;
  167.   }
  168.  
  169.   // Reallocate the 32K block to the actually needed size
  170.   GlobalUnlock(hMem);
  171.   GlobalReAlloc(hMem, clipboard-clipboardStart, 0);
  172.  
  173.   // Set a clipboard handle to point to the copied block data
  174.   OpenClipboard(hMainWnd);
  175.   EmptyClipboard();
  176.   SetClipboardData(CF_PRIVATEFIRST, hMem);
  177.   CloseClipboard();
  178. }
  179.  
  180. // **********************************************
  181. // PasteBlock pastes the block whose handle is in the clipboard
  182. // to the given (staff,X) coordinate.
  183.  
  184. void PasteBlock(int pasteStaff, int pasteX)
  185. {
  186.   // Obtain a pointer to the clipboard entry
  187.   OpenClipboard(hMainWnd);
  188.   GLOBALHANDLE hMem = GetClipboardData(CF_PRIVATEFIRST);
  189.   if (!hMem)
  190.     return;
  191.   char far *clipboard = GlobalLock(hMem);
  192.   Part &p = *((Part *) &melody.part[displayedPart]);
  193.  
  194.   // Read the block parameters
  195.   if (*((int far *) clipboard)++ != p.multiplicity())
  196.     MessageBox(hEditWnd, "Cannot paste block - different staff multiplicity",
  197.       NULL, MB_OK);
  198.   else {
  199.     // Read the block parameters to variables
  200.     int staffDiff = *((int far *) clipboard)++;
  201.     int beginX = *((int far *) clipboard)++;
  202.     int endX = *((int far *) clipboard)++;
  203.     pasteX = pasteX+endX-beginX < melody.GetStaffWidth() ? pasteX :
  204.       melody.GetStaffWidth()-endX+beginX-1;
  205.     BOOL singleStaffBlock = !staffDiff;
  206.  
  207.     // Paste a single-staff or a multiple-staff block
  208.     // Add the height of the pasted block to all subsequent staves
  209.     for (int index = pasteStaff+p.multiplicity();
  210.       index < p.staff.number(); ++index)
  211.       ((Staff *) &p.staff[index])->Y() += staffDiff*pixelsPerStaff;
  212.  
  213.     // The loop of pasting staves
  214.     staffDiff += p.multiplicity()-1;
  215.     index = pasteStaff;
  216.     int staffY = ((Staff *) &p.staff[index])->Y();
  217.     do {
  218.       // If needed, insert a new staff into the melody
  219.       if (index/p.multiplicity()*p.multiplicity() > pasteStaff)
  220.         p.staff.insertAt(*new Staff(staffY += pixelsPerStaff), index);
  221.       Staff &s = *((Staff *) &p.staff[index]);
  222.       int type;
  223.  
  224.       // As long as the staff end is not reached, paste objects
  225.       while (*clipboard != STAFF) {
  226.         // Create an object from the information in the clipboard
  227.         MusicalObject *m = PasteObject((void far *) clipboard, &type);
  228.         switch (type) {
  229.           case POINTOBJECT:
  230.             // If the block is less than a single staff,
  231.             // adjust the X coordinate of the pasted point object
  232.             int X = ((PointObject *) m)->X();
  233.             X += singleStaffBlock ? pasteX-beginX : 0;
  234.             for (int i = 0;
  235.               i < s.pointObject.number() &&
  236.                 ((PointObject *) &s.pointObject[i])->X() <= X;
  237.               ++i);
  238.             // Insert the object into the point object list
  239.             s.pointObject.insertAt(*m, i);
  240.             ((PointObject *) m)->X() = X;
  241.             break;
  242.  
  243.           case CONTINUOUSOBJECT:
  244.             // If the block is less than a single staff,
  245.             // adjust the X coordinates of the pasted continuous object
  246.             X = ((ContinuousObject *) m)->Xleft();
  247.             X += singleStaffBlock ? pasteX-beginX : 0;
  248.             for (i = 0;
  249.               i < s.continuousObject.number() &&
  250.                 ((ContinuousObject *) &s.continuousObject[i])->Xleft() <= X;
  251.               ++i);
  252.             // Insert the object into the continuous object list
  253.             s.continuousObject.insertAt(*m, i);
  254.             ((ContinuousObject *) m)->Xright() += X-((ContinuousObject *) m)->Xleft();
  255.             ((ContinuousObject *) m)->Xleft() = X;
  256.             break;
  257.         }
  258.       }
  259.       ++clipboard;
  260.       ++index;
  261.     } while (--staffDiff >= 0);
  262.   }
  263.  
  264.   // Unlock the handle
  265.   GlobalUnlock(hMem);
  266. }
  267.